#ifndef LENGTH_H
#define LENGTH_H
#ifndef _EXPECT_BYTES_LENGTH
#define _EXPECT_BYTES_LENGTH 2
#endif

#include <compile.h>

#include "recurse_macro.h"

#define _GetProcess(len)     (len.data_[EXPECT_BYTES_LENGTH - 2])
#define _GerAddress(len)     (len.data_[EXPECT_BYTES_LENGTH - 1])

#define HIGHB(n)			(0xFFFFFFFF << (sizeof(_ptlong)*8 - n))
#define LOWB(n)				(0xFFFFFFFF >> (sizeof(_ptlong)*8 - n))

#define _EXPAND_LEN(_len,num)  (_len->data_[num]) 
#define EXPAND_LENGTH_MEMBER(_LEN)  __JOIN__(RECURSE_C_,_EXPECT_BYTES_LENGTH)(_LEN,_EXPAND_LEN)

#define _len _CUSTOMIZED_INTEGRATED
namespace
{
  template<int N>
    struct __runner
    {
    
      template<typename T,typename ...Args>
      static inline void run(T fun,Args... args)
      {
	fun(N,args...);__runner<N-1>::run(fun,args...);
      }
    };
      
  
  template<>
    struct __runner<0>
    {
      
      template<typename T,typename ...Args>
	static inline void run(T fun,Args... args)
      {
	fun(0,args...);
      }
    };


inline _longest _len_to_longest(const volatile _ptlong* a)
{
  _longest ret = 0;
  return (__runner<_EXPECT_BYTES_LENGTH>::run([](int N,const volatile _ptlong* a,_longest& ret)->void{ret |= a[N] << (N * BYTE_SIZE);},a,ret),ret); 
}
inline _longest _len_to_longest(const _ptlong* a)
{
  _longest ret = 0;
  return (__runner<_EXPECT_BYTES_LENGTH>::run([](int N,const _ptlong* k,_longest& ret)->void{ret |= k[N] << (N * BYTE_SIZE);},a,ret),ret); 
}

inline void _longest_to_len(_ptlong* a,const _longest l)
{
  (__runner<_EXPECT_BYTES_LENGTH>::run([](int N,_ptlong* k,const _longest c)->void{k[N] = __force_cast(type_as_argv(_ptlong),(c >> (N * BYTE_SIZE)));},
					      a,l));
}
}

struct _len
{
  constexpr _len(){data_[0] = 0;}
  constexpr  explicit _len(_ptlong* k){(({for(int i = 0; i < _EXPECT_BYTES_LENGTH ; i++)data_[i] = k[i];}),1);}
  constexpr _len(const _longest k){_longest_to_len(data_,k);} 
  _ptlong data_[_EXPECT_BYTES_LENGTH];
    
  inline const volatile operator _longest()const volatile {return _len_to_longest(data_);}
  inline const volatile operator _longest()volatile {return _len_to_longest(data_);}
  inline const operator _longest()const {return _len_to_longest(data_);}
  inline const operator _longest() {return _len_to_longest(data_);}
  inline volatile operator _ptlong() const volatile{return this->data_[0];}
  inline operator _ptlong() const{return this->data_[0];}
  
  inline const _len& operator=(const _ptlong x){data_[0] = x;return *this;}

    inline volatile const _len& operator=(volatile const _ptlong x)volatile {data_[0] = x;return *this;}

template<typename T>
inline _len operator+=(const T x){return ((data_[0] += (_ptlong)x),*this);}
template<typename T>
inline volatile _len operator+=(const T x)volatile{return ((_ptlong)(data_[0] += (_ptlong)x),*this);}
template<typename T>
inline _len operator-=(const T x){return ((data_[0] -= (_ptlong)x),*this);}
template<typename T>
inline volatile _len operator-=(const T x)volatile{return ((data_[0] -= (_ptlong)x),*this);}
template<typename T>
inline _len operator&=(const T x){return ((data_[0] &= (_ptlong)x),*this);}
template<typename T>
inline volatile _len operator&=(const T x)volatile{return ((data_[0] &= (_ptlong)x),*this);}
template<typename T>
inline _len operator|=(const T x){return ((data_[0] |= (_ptlong)x),*this);}
template<typename T>
inline volatile _len operator|=(const T x)volatile{return ((data_[0] |= (_ptlong)x),*this);}


};



//the data_[0] = 0~32 data[1] = 33 ~ 34


typedef struct _len  ___LENGTH;

#define _length  ___LENGTH



  static constexpr _length _OneRightMove(_length len,unsigned int num = _EXPECT_BYTES_LENGTH)
  {
    return (num == 1
	    ?(((len.data_[1] = len.data_[0]),(len.data_[0] = 0)),len)
	    :((len.data_[num] = len.data_[num - 1]),_OneRightMove(len,num-1)));
  }

  static constexpr _length RightMove(_length len,unsigned int num)
  {
    return (num > 0
	    ? RightMove(_OneRightMove(len),num-1)
	    : len);
  }



/*

template<unsigned int... Args>class _MAKE_LENGTH{};

template<unsigned int arg,unsigned int ... Args>
  class _MAKE_LENGTH<arg,Args...>
{public:
  constexpr static _length Fun(_length len={{0}},unsigned int num = 0)
  {
    return (num < _EXPECT_BYTES_LENGTH 
	    ? (len.data_[num] = arg,_MAKE_LENGTH<Args...>::Fun(len,num+1))
	    :len);
  }
};
template <>
class _MAKE_LENGTH<>
{public:
  constexpr static _length Fun(_length len={{0}},unsigned int num = 0)
  {
    return (RightMove(len,_EXPECT_BYTES_LENGTH - num - 1));
  }
};


template<unsigned int ... Args>
constexpr _length Makelength()
{
  return _MAKE_LENGTH<Args...>::Fun();
}

inline _length Makelength(_ptlong num);

*/
//#define Makelength(x) (x)



/*
inline bool operator>(volatile const _length& lenA,volatile  const _length& lenB);
inline bool operator==(volatile const _length& lenA,volatile const _length& lenB);
inline bool operator<(volatile const _length& lenA,volatile const _length& lenB);
inline bool operator<=(volatile const _length& lenA,volatile const _length& lenB);
inline bool operator>=(volatile const _length& lenA,volatile const _length& lenB);
inline _length operator+(volatile const _length& lenA,volatile const _length& lenB);
inline _length operator~(volatile const _length& len);
inline _length operator&(volatile const _length& a,volatile const _length& b);
inline _length operator^(volatile const _length& a,volatile const _length& b);
inline _ptlong operator%(volatile const _length& lenA,_ptlong num);
*/

#endif
